home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 151-175 / 169 / src / shell / sub.c < prev    next >
C/C++ Source or Header  |  1995-03-13  |  12KB  |  556 lines

  1.  
  2. /*
  3.  * SUB.C
  4.  *
  5.  * (C)Copyright 1987 Matthew Dillon,    All rights reserved
  6.  *
  7.  *      Subroutines used throughout the shell (not very descriptive, am I?)
  8.  */
  9.  
  10.  
  11. #include <exec/types.h>
  12. #include <libraries/dos.h>
  13. #include <libraries/dosextens.h>
  14. #include "shell.h"
  15.  
  16. #define HM_STR 0              /* various HISTORY retrieval modes */
  17. #define HM_REL 1
  18. #define HM_ABS 2
  19.  
  20. extern struct FileLock *Lock(), *DupLock(), *CurrentDir();
  21. extern struct FileLock *Clock;
  22.  
  23. seterr()
  24. {
  25.     char buf[32];
  26.     int stat;
  27.  
  28.     sprintf(buf, "%ld", Lastresult);
  29.     set_var(LEVEL_SET, V_LASTERR, buf);
  30.     stat = atoi(get_var(LEVEL_SET, V_STAT));
  31.     if (stat < Lastresult)
  32.         stat = Lastresult;
  33.     sprintf(buf, "%ld", stat);
  34.     set_var(LEVEL_SET, V_STAT, buf);
  35. }
  36.  
  37.  
  38. char *
  39. next_word(str)
  40. register char *str;
  41. {
  42.     while (*str  &&  *str != ' '  &&  *str != 9)
  43.         ++str;
  44.     while (*str  && (*str == ' ' || *str == 9))
  45.         ++str;
  46.     return (str);
  47. }
  48.  
  49.  
  50. char *
  51. compile_av(av, start, end)
  52. short start, end;
  53. char **av;
  54. {
  55.     char *cstr;
  56.     short i, len;
  57.  
  58.     len = 0;
  59.     for (i = start; i < end; ++i)
  60.         len += strlen(av[i]) + 1;
  61.     cstr = malloc(len + 1);
  62.     *cstr = '\0';
  63.     for (i = start; i < end; ++i) {
  64.         strcat (cstr, av[i]);
  65.         strcat (cstr, " ");
  66.     }
  67.     return (cstr);
  68. }
  69.  
  70. /*
  71.  * FREE(ptr)   --frees without actually freeing, so the data is still good
  72.  *               immediately after the free.
  73.  */
  74.  
  75.  
  76. Free(ptr)
  77. char *ptr;
  78. {
  79.     static char *old_ptr;
  80.  
  81.     if (old_ptr)
  82.         free (old_ptr);
  83.     old_ptr = ptr;
  84. }
  85.  
  86. /*
  87.  * Add new string to history (H_head, H_tail, H_len,
  88.  *  S_histlen
  89.  */
  90.  
  91. add_history(str)
  92. char *str;
  93. {
  94.     register struct HIST *hist;
  95.  
  96.     while (H_len > S_histlen)
  97.         del_history();
  98.     hist = (struct HIST *)malloc (sizeof(struct HIST));
  99.     if (H_head == NULL) {
  100.         H_head = H_tail = hist;
  101.         hist->next = NULL;
  102.     } else {
  103.         hist->next = H_head;
  104.         H_head->prev = hist;
  105.         H_head = hist;
  106.     }
  107.     hist->prev = NULL;
  108.     hist->line = malloc (strlen(str) + 1);
  109.     strcpy (hist->line, str);
  110.     ++H_len;
  111. }
  112.  
  113. del_history()
  114. {
  115.     if (H_tail) {
  116.         --H_len;
  117.         ++H_tail_base;
  118.         free (H_tail->line);
  119.         if (H_tail->prev) {
  120.             H_tail = H_tail->prev;
  121.             free (H_tail->next);
  122.             H_tail->next = NULL;
  123.         } else {
  124.             free (H_tail);
  125.             H_tail = H_head = NULL;
  126.         }
  127.     }
  128. }
  129.  
  130.  
  131. char *
  132. last_history_entry()
  133. {
  134.     if (H_head)
  135.         return(H_head->line);
  136.     return("");
  137. }
  138.  
  139.  
  140. char *
  141. get_history(ptr)
  142. char *ptr;
  143. {
  144.     register struct HIST *hist;
  145.     register short len;
  146.     short mode = HM_REL;
  147.     long num  = 1;
  148.     char *str;
  149.     char *result = NULL;
  150.  
  151.     if (ptr[1] >= '0' && ptr[1] <= '9') {
  152.         mode = HM_ABS;
  153.         num  = atoi(&ptr[1]);
  154.         goto skip;
  155.     }
  156.     switch (ptr[1]) {
  157.     case '!':
  158.         break;
  159.     case '-':
  160.         num += atoi(&ptr[2]);
  161.         break;
  162.     default:
  163.         mode = HM_STR;
  164.         str  = ptr + 1;
  165.         break;
  166.     }
  167. skip:
  168.     switch (mode) {
  169.     case HM_STR:
  170.         len = strlen(str);
  171.         for (hist = H_head; hist; hist = hist->next) {
  172.             if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') {
  173.                 result = hist->line;
  174.                 break;
  175.             }
  176.         }
  177.         break;
  178.     case HM_REL:
  179.         for (hist = H_head; hist && num--; hist = hist->next);
  180.         if (hist)
  181.             result = hist->line;
  182.         break;
  183.     case HM_ABS:
  184.         len = H_tail_base;
  185.         for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
  186.         if (hist)
  187.             result = hist->line;
  188.         break;
  189.     }
  190.     if (result) {
  191.         Eputs (result);
  192.         return(result);
  193.     }
  194.     Eputs ("History substitution failed");
  195.     return ("");
  196. }
  197.  
  198.  
  199. replace_head(str)
  200. char *str;
  201. {
  202.     if (str == NULL)
  203.         str = "";
  204.     if (H_head) {
  205.         free (H_head->line);
  206.         H_head->line = malloc (strlen(str)+1);
  207.         strcpy (H_head->line, str);
  208.     }
  209. }
  210.  
  211. perror(str)
  212. char *str;
  213. {
  214.     ierror(str, IoErr());
  215. }
  216.  
  217. ierror(str, err)
  218. register char *str;
  219. short err;
  220. {
  221.     register struct PERROR *per = Perror;
  222.  
  223.     if (err) {
  224.         for (; per->errstr; ++per) {
  225.             if (per->errnum == err) {
  226.                 fhprintf (Cerr, "%s%s%s\n",
  227.                     per->errstr,
  228.                     (str) ? ": " : "",
  229.                     (str) ? str : ""
  230.                 );
  231.                 return(err);
  232.             }
  233.         }
  234.         fhprintf (Cerr, "Unknown DOS error %ld %s\n", err, (str) ? str : "");
  235.    }
  236.    return (err);
  237. }
  238.  
  239. /*
  240.  * Disk directory routines
  241.  *
  242.  * dptr = dopen(name, stat)
  243.  *    struct DPTR *dptr;
  244.  *    char *name;
  245.  *    int *stat;
  246.  *
  247.  * dnext(dptr, name, stat)
  248.  *    struct DPTR *dptr;
  249.  *    char **name;
  250.  *    int  *stat;
  251.  *
  252.  * dclose(dptr)                  -may be called with NULL without harm
  253.  *
  254.  * dopen() returns a struct DPTR, or NULL if the given file does not
  255.  * exist.  stat will be set to 1 if the file is a directory.  If the
  256.  * name is "", then the current directory is openned.
  257.  *
  258.  * dnext() returns 1 until there are no more entries.  The **name and
  259.  * *stat are set.  *stat = 1 if the file is a directory.
  260.  *
  261.  * dclose() closes a directory channel.
  262.  *
  263.  */
  264.  
  265. struct DPTR *
  266. dopen(name, stat)
  267. char *name;
  268. register int *stat;
  269. {
  270.     register struct DPTR *dp;
  271.  
  272.     *stat = 0;
  273.     dp = (struct DPTR *)malloc(sizeof(struct DPTR));
  274.     if (*name == '\0')
  275.         dp->lock = DupLock (Clock);
  276.     else
  277.         dp->lock = Lock (name, ACCESS_READ);
  278.     if (dp->lock == NULL) {
  279.         free (dp);
  280.         return (NULL);
  281.     }
  282.     dp->fib = (struct FileInfoBlock *)
  283.             AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC);
  284.     if (!Examine (dp->lock, dp->fib)) {
  285.         perror (name);
  286.         dclose (dp);
  287.         return (NULL);
  288.     }
  289.     if (dp->fib->fib_DirEntryType >= 0)
  290.         *stat = 1;
  291.     return (dp);
  292. }
  293.  
  294. dnext(dp, pname, stat)
  295. register struct DPTR *dp;
  296. char **pname;
  297. int *stat;
  298. {
  299.     if (dp == NULL)
  300.         return (0);
  301.     if (ExNext (dp->lock, dp->fib)) {
  302.         *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
  303.         *pname = dp->fib->fib_FileName;
  304.         return (1);
  305.     }
  306.     return (0);
  307. }
  308.  
  309.  
  310. dclose(dp)
  311. register struct DPTR *dp;
  312. {
  313.     if (dp == NULL)
  314.         return (1);
  315.     if (dp->fib)
  316.         FreeMem (dp->fib, sizeof(*dp->fib));
  317.     if (dp->lock)
  318.         UnLock (dp->lock);
  319.     free (dp);
  320.     return (1);
  321. }
  322.  
  323.  
  324. isdir(file)
  325. char *file;
  326. {
  327.     register struct DPTR *dp;
  328.     int stat;
  329.  
  330.     stat = 0;
  331.     if (dp = dopen (file, &stat))
  332.         dclose(dp);
  333.     return (stat == 1);
  334. }
  335.  
  336.  
  337. free_expand(av)
  338. register char **av;
  339. {
  340.     register char **base = av;
  341.  
  342.     if (av) {
  343.         while (*av) {
  344.             free (*av);
  345.             ++av;
  346.         }
  347.         free (base);
  348.     }
  349. }
  350.  
  351. /*
  352.  * EXPAND(wild_name, pac)
  353.  *    wild_name      - char * (example: "df0:*.c")
  354.  *    pac            - int  *  will be set to # of arguments.
  355.  *
  356.  * Standalone, except in requires Clock to point to the Current-Directory
  357.  * lock.
  358.  */
  359.  
  360.  
  361. char **
  362. expand(base, pac)
  363. char *base;
  364. int *pac;
  365. {
  366.     register char *ptr;
  367.     char **eav = (char **)malloc (sizeof(char *));
  368.     short eleft, eac;
  369.     char *name;
  370.     char *bname, *ename, *tail;
  371.     int stat, scr;
  372.     register struct DPTR *dp;
  373.  
  374.     *pac = eleft = eac = 0;
  375.  
  376.     base = strcpy(malloc(strlen(base)+1), base);
  377.     for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
  378.     for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
  379.     if (ptr < base) {
  380.         bname = strcpy (malloc(1), "");
  381.     } else {
  382.         scr = ptr[1];
  383.         ptr[1] = '\0';
  384.         bname = strcpy (malloc(strlen(base)+1), base);
  385.         ptr[1] = scr;
  386.     }
  387.     ename = ptr + 1;
  388.     for (ptr = ename; *ptr && *ptr != '/'; ++ptr);
  389.     scr = *ptr;
  390.     *ptr = '\0';
  391.     tail = (scr) ? ptr + 1 : NULL;
  392.  
  393.     if ((dp = dopen (bname, &stat)) == NULL  ||  stat == 0) {
  394.         free (bname);
  395.         free (base);
  396.         free (eav);
  397.         Eputs ("Could not open directory");
  398.         return (NULL);
  399.     }
  400.     while (dnext (dp, &name, &stat)) {
  401.         if (compare_ok(ename, name)) {
  402.             if (tail) {
  403.                 int alt_ac;
  404.                 char *search, **alt_av, **scrav;
  405.                 struct FileLock *lock;
  406.  
  407.                 if (!stat)           /* expect more dirs, but this not a dir */
  408.                     continue;
  409.                 lock = CurrentDir (Clock = dp->lock);
  410.                 search = malloc(strlen(name)+strlen(tail)+2);
  411.                 strcpy (search, name);
  412.                 strcat (search, "/");
  413.                 strcat (search, tail);
  414.                 scrav = alt_av = expand (search, &alt_ac);
  415.                 CurrentDir (Clock = lock);
  416.                 if (scrav) {
  417.                     while (*scrav) {
  418.                         if (eleft < 2) {
  419.                             char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  420.                             bmov (eav, scrav, (eac + 1) << 2);
  421.                             free (eav);
  422.                             eav = scrav;
  423.                             eleft = 10;
  424.                         }
  425.                         eav[eac] = malloc(strlen(bname)+strlen(*scrav)+1);
  426.                         strcpy(eav[eac], bname);
  427.                         strcat(eav[eac], *scrav);
  428.                         free (*scrav);
  429.                         ++scrav;
  430.                         --eleft, ++eac;
  431.                     }
  432.                     free (alt_av);
  433.                 }
  434.             } else {
  435.                 if (eleft < 2) {
  436.                     char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  437.                     bmov (eav, scrav, (eac + 1) << 2);
  438.                     free (eav);
  439.                     eav = scrav;
  440.                     eleft = 10;
  441.                 }
  442.                 eav[eac] = malloc (strlen(bname)+strlen(name)+1);
  443.                 eav[eac] = strcpy(eav[eac], bname);
  444.                 strcat(eav[eac], name);
  445.                 --eleft, ++eac;
  446.             }
  447.         }
  448.     }
  449.     dclose (dp);
  450.     *pac = eac;
  451.     eav[eac] = NULL;
  452.     free (bname);
  453.     free (base);
  454.     if (eac)
  455.         return (eav);
  456.     free (eav);
  457.     return (NULL);
  458. }
  459.  
  460. /*
  461.  * Compare a wild card name with a normal name
  462.  */
  463.  
  464. #define MAXB   8
  465.  
  466. compare_ok(wild, name)
  467. char *wild, *name;
  468. {
  469.     register char *w = wild;
  470.     register char *n = name;
  471.     char *back[MAXB][2];
  472.     register char s1, s2;
  473.     register short bi = 0;
  474.  
  475.     while (*n || *w) {
  476.         switch (*w) {
  477.         case '*':
  478.             if (bi == MAXB) {
  479.                 Eputs ("Too many levels of '*'");
  480.                 return (0);
  481.             }
  482.             back[bi][0] = w;
  483.             back[bi][1] = n;
  484.             ++bi;
  485.             ++w;
  486.             continue;
  487. goback:
  488.             --bi;
  489.             while (bi >= 0 && *back[bi][1] == '\0')
  490.                 --bi;
  491.             if (bi < 0)
  492.                 return (0);
  493.             w = back[bi][0] + 1;
  494.             n = ++back[bi][1];
  495.             ++bi;
  496.             continue;
  497.         case '?':
  498.             if (!*n) {
  499.                 if (bi)
  500.                     goto goback;
  501.                 return (0);
  502.             }
  503.             break;
  504.         default:
  505.             s1 = (*n >= 'A' && *n <= 'Z') ? *n - 'A' + 'a' : *n;
  506.             s2 = (*w >= 'A' && *w <= 'Z') ? *w - 'A' + 'a' : *w;
  507.             if (s1 != s2) {
  508.                 if (bi)
  509.                     goto goback;
  510.                 return (0);
  511.             }
  512.             break;
  513.         }
  514.         if (*n)  ++n;
  515.         if (*w)  ++w;
  516.     }
  517.     return (1);
  518. }
  519.  
  520.  
  521. Oputs(str)
  522. char *str;
  523. {
  524.     Write (Cout, str, strlen(str));
  525.     Write (Cout, "\n", 1);
  526. }
  527.  
  528. Eputs(str)
  529. char *str;
  530. {
  531.     Write (Cerr, str, strlen(str));
  532.     Write (Cerr, "\n", 1);
  533. }
  534.  
  535. char *
  536. Ogets(str)
  537. char *str;
  538. {
  539.     register int i = 0;
  540.  
  541.     while (Read(Cin, str + i, 1) == 1) {
  542.         if (str[i] == '\n') {
  543.             str[i] = 0;
  544.             return (str);
  545.         }
  546.         if (++i == 255) {
  547.             str[i] = 0;
  548.             return (str);
  549.         }
  550.     }
  551.     return (NULL);
  552. }
  553.  
  554.  
  555.  
  556.